from datetime import timedelta, datetime

import requests
from fastapi import HTTPException
from jose import jwt
from starlette import status

from configs import SECRET_KEY, ACCESS_TOKEN_EXPIRE_MINUTES, ALGORITHM, WX_APP_ID, \
    WX_APP_SECRET, WX_TOKEN_URL, WX_PHONE_URL


credentials_exception = HTTPException(
    status_code=status.HTTP_401_UNAUTHORIZED,
    detail="非法token",
    headers={"WWW-Authenticate": "Bearer"},
)


def get_wx_access_token():
    """
    获取微信小程序的 access_token
    """
    params = {
        'grant_type': 'client_credential',
        'appid': WX_APP_ID,
        'secret': WX_APP_SECRET
    }
    try:
        # 发送 GET 请求
        response = requests.get(WX_TOKEN_URL, params=params)
        response.raise_for_status()  # 检查请求是否成功
        wx_data = response.json()

        # 检查返回结果
        if 'errcode' in wx_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"获取 access_token 失败: {wx_data.get('errmsg')}"
            )

        # 返回 access_token
        return wx_data.get('access_token')

    except requests.exceptions.RequestException as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"请求微信接口失败: {str(e)}"
        )


def get_user_phone_number(code: str):
    """
    通过 code 获取用户手机号
    """
    # 获取 access_token
    access_token = get_wx_access_token()
    if not access_token:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="获取 access_token 失败"
        )

    # 调用微信接口获取手机号
    url = f"{WX_PHONE_URL}?access_token={access_token}"
    payload = {"code": code}
    try:
        response = requests.post(url, json=payload)
        response.raise_for_status()
        wx_data = response.json()

        # 解析返回结果
        if wx_data.get("errcode") != 0:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"获取手机号失败: {wx_data.get('errmsg')}"
            )

        # 返回手机号信息
        return wx_data.get('phone_info').get('phoneNumber')

    except requests.exceptions.RequestException as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"请求微信接口失败: {str(e)}"
        )


def create_access_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    expire = datetime.now() + (expires_delta if expires_delta else timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt
